﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using Icoders.MarketTracker.Core.MasterData;
using Icoders.MarketTracker.Core.Repository.MasterDataRepositories;
using Icoders.MarketTracker.Core.Validation;
using Icoders.MarketTracker.Data.EF;
using Icoders.MarketTracker.Data.Utils;
using Icoders.MarketTracker.Data.Utils.Caching;

namespace Icoders.MarketTracker.Data.Repository.MasterDataRepositories
{
    public class ClientRepository :RepositoryBase,IClientRepository
    {
         private AppDataContext _ctx;
         private ICacheProvider _cacheProvider;

        public ClientRepository(AppDataContext ctx, ICacheProvider cacheProvider)
        {
            _ctx = ctx;
            _cacheProvider = cacheProvider;
        }

        public int Save(Client entity)
       {
           ValidationResultInfo vri = Validate(entity);
           if(!vri.IsValid)
           {
               throw new DomainValidationException(vri, "Area Details provided not Valid");
           }
           DateTime date = TimeUtil.GetDateTime();
           TblClient tbl= _ctx.TblClient.FirstOrDefault(s => s.Id == entity.Id);
           if (tbl == null)
           {
               tbl = new TblClient();
               tbl.CreatedOn = date;
               tbl.StatusId = (int) MasterEntityStatus.New;
               _ctx.TblClient.AddObject(tbl);
               tbl.Code = entity.Code;
               tbl.Description = entity.Description;
           }
           tbl.UpdatedOn = date;
           tbl.Name = entity.Name;
           _ctx.SaveChanges();
           _cacheProvider.Put(_cacheListKey, _ctx.TblClient.Where(x => x.StatusId != 3).Select(s => s.Id).ToList());
           _cacheProvider.Remove(string.Format(_cacheKey, tbl.Id));
           return tbl.Id;
       }

       public Client GetById(int id)
       {
           Client entity = (Client)_cacheProvider.Get(string.Format(_cacheKey, id));
           if (entity == null)
           {
               var tbl = _ctx.TblClient.FirstOrDefault(s => s.Id == id);
               if (tbl != null)
               {
                   entity = Map(tbl);
                   _cacheProvider.Put(string.Format(_cacheKey, entity.Id), entity);
               }

           }
           return entity;
       }

       public List<Client> GetAll()
       {
           //return _ctx.TblClient.ToList().Where(p => p.StatusId != (int)MasterEntityStatus.Deleted).Select(n => Map(n)).ToList();
           IList<Client> entities = null;
           IList<int> ids = (IList<int>)_cacheProvider.Get(_cacheListKey);
           if (ids != null)
           {
               entities = new List<Client>(ids.Count);
               foreach (int id in ids)
               {
                   Client entity = GetById(id);
                   if (entity != null)
                       entities.Add(entity);
               }
           }
           else
           {
               entities = _ctx.TblClient.Where(x => x.StatusId != 3).ToList().Select(s => Map(s)).ToList();
               if (entities != null && entities.Count > 0)
               {
                   ids = entities.Select(s => s.Id).ToList(); //new List<int>(persons.Count);
                   _cacheProvider.Put(_cacheListKey, ids);
                   foreach (Client p in entities)
                   {
                       _cacheProvider.Put(string.Format(_cacheKey, p.Id), p);
                   }

               }
           }
           return entities.ToList();
       }

        public void Delete(int id)
        {
            var tbl = _ctx.TblClient.FirstOrDefault(s => s.Id == id);
            if (tbl != null)
            {
                tbl.StatusId = (int)MasterEntityStatus.Deleted;
                _ctx.SaveChanges();
                _cacheProvider.Put(_cacheListKey, _ctx.TblClient.Where(x => x.StatusId != 3).Select(s => s.Id).ToList());
                _cacheProvider.Remove(string.Format(_cacheKey, tbl.Id));
            }
        }

        private Client Map(TblClient tblClient)
       {
           return new Client() //(tblCountry.Id)
           {
               Id = tblClient.Id,
               Code = tblClient.Code,
               Name = tblClient.Name,
               Description = tblClient.Description,
               UpdatedOn = tblClient.UpdatedOn,
               CreatedOn = tblClient.CreatedOn,
               Status = (MasterEntityStatus)tblClient.StatusId

           };
       }

       public ValidationResultInfo Validate(Client objToValidate)
       {
           ValidationResultInfo vri = objToValidate.BasicValidation();
           bool hasDuplicateName = GetAll().Where(v => v.Id != objToValidate.Id)
               .Any(p => p.Name == objToValidate.Name);
           if (hasDuplicateName)
               vri.Results.Add(new ValidationResult("Duplicate Name Found"));
           return vri;
       }

        protected override string _cacheKey
        {
            get { return "Client-{0}"; }
        }

        protected override string _cacheListKey
        {
            get { return "ClientList"; }
        }
    }
}
